package com.alibaba.citrus.cr.mn.order.center.facade.function.common;

import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.util.ThreadPoolUtil;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.function.assemble.OrderBizAssemble;
import com.alibaba.citrus.cr.mn.order.center.facade.function.assemble.impl.OrderUpdateBizAssembleOfMemberCenter;
import com.alibaba.cz.base.tool.TenantUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.trace.TraceUtil;
import com.alibaba.cz.base.tool.trace.thread.CustomTraceThreadLocal;
import com.alibaba.cz.base.tool.trace.thread.TraceParam;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crb2btradecenter.enums.OrderStatus;
import com.epoch.app.mnordercenter.orderbaserequest.OrderAtomUpdateResponse;
import com.epoch.app.mnordercenter.orderbaserequest.OrderBizUpdateRequest;
import com.epoch.app.mnordercenter.orderbaserequest.OrderLineAtomCreateResponse;
import com.epoch.app.mnordercenter.orderbaserequest.OrderLineAtomUpdateRequest;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;

/**
 * @author zhangxiaorui
 * @date 2023/05/16 14:07
 */
public abstract class AbstractOrderBizUpdateService {

    private static final Log log = Log.getLogger(AbstractOrderBizUpdateService.class);

    @Resource
    private List<OrderBizAssemble<OrderBizUpdateRequest>> orderBizAssembles;
    @Resource
    OrderUpdateBizAssembleOfMemberCenter orderUpdateBizAssembleOfMemberCenter;

    public void preHandleRequestParams(OrderBizUpdateRequest bizUpdateRequest) {
        if (StringUtils.isBlank(bizUpdateRequest.getBusinessUnitCode())
                || StringUtils.isBlank(bizUpdateRequest.getBusinessType())
                || StringUtils.isBlank(bizUpdateRequest.getFromSys())) {
            return;
        }
        bizUpdateRequest.setOrderDetails(Optional.ofNullable(bizUpdateRequest.getOrderDetails()).orElse(Lists.newArrayList()));
        for (OrderLineAtomUpdateRequest orderLineAtomUpdateRequest : bizUpdateRequest.getOrderDetails()) {
            orderLineAtomUpdateRequest.setBusinessUnitCode(bizUpdateRequest.getBusinessUnitCode());
            orderLineAtomUpdateRequest.setBusinessType(bizUpdateRequest.getBusinessType());
            orderLineAtomUpdateRequest.setFromSys(bizUpdateRequest.getFromSys());
        }
    }

    public OrderAtomUpdateResponse assembleBizBaseInfo(OrderBizUpdateRequest orderBizUpdateRequest) {
        log.info("AbstractOrderBizUpdateService#assembleBizBaseInfo orderBizUpdateRequest={}", orderBizUpdateRequest);

        // 中心数据并行查询（eg：库存中心、商品中心、客户中心 等等）
        Map<String, Object> queryResponseMap = Maps.newConcurrentMap();

        // 非待提交/待推送状态订单，只用校验修改人信息
        if (!OrderStatus.BEFORE_SUBMIT.getCode().equals(orderBizUpdateRequest.getStatus())
                && !OrderStatus.STAY_PUSH.getCode().equals(orderBizUpdateRequest.getStatus())) {
            StopWatchUtils.start("订单中心商业修改", "queryEmployee");
            Map<String, Object> queryResult = orderUpdateBizAssembleOfMemberCenter.query(orderBizUpdateRequest);
            queryResponseMap.putAll(queryResult);
            orderUpdateBizAssembleOfMemberCenter.assemble(queryResponseMap, orderBizUpdateRequest);
            StopWatchUtils.stop();
            return null;
        }
        return assembleBizBaseInfoNew(orderBizUpdateRequest, queryResponseMap);
    }

    public OrderAtomUpdateResponse assembleBizBaseInfoNew(OrderBizUpdateRequest orderBizUpdateRequest, Map<String, Object> queryResponseMap) {
        log.info("AbstractOrderBizUpdateService#assembleBizBaseInfo orderBizUpdateRequest={}", orderBizUpdateRequest);
        CountDownLatch countDownLatch = new CountDownLatch(orderBizAssembles.size());
        try {
            StopWatchUtils.start("订单中心商业修改", "assembleQuery");
            String traceId = TraceUtil.getTraceId();
            String tenantId = TenantUtil.getTenantId();
            for (OrderBizAssemble<OrderBizUpdateRequest> orderBizAssemble : orderBizAssembles) {
                ThreadPoolUtil.execute(() -> {
                    try {
                        TraceParam traceParam = new TraceParam();
                        traceParam.setTraceId(traceId);
                        traceParam.setTenantId(tenantId);
                        CustomTraceThreadLocal.set(traceParam);
                        Map<String, Object> queryResult = orderBizAssemble.query(orderBizUpdateRequest);
                        queryResponseMap.putAll(queryResult);
                    } finally {
                        countDownLatch.countDown();
                        // 清理当前子线程的traceId
                        CustomTraceThreadLocal.clean();
                    }
                });
            }
            countDownLatch.await();
        } catch (Exception e) {
            log.error("AbstractOrderBizUpdateService#assembleBizBaseInfo query error", e);
            throw new FunctionException(e);
        } finally {
            StopWatchUtils.stop();
        }

        log.info("AbstractOrderBizUpdateService#assembleBizBaseInfo orderBizAssembles size:{}", orderBizAssembles.size());
        // 业务数据同步-校验&组装
        // 按主单维度Order顺序进行数据组装
        try {
            StopWatchUtils.start("订单中心商业修改", "assemble");
            for (OrderBizAssemble<OrderBizUpdateRequest> orderBizAssemble : orderBizAssembles) {
                // 数据组装校验失败时，跳出当前组装逻辑，进行下一主单数据组装
                log.info("AbstractOrderBizUpdateService#assembleBizBaseInfo queryResponseMap:{}; orderBizUpdateRequest:{}", JSON.toJSONString(queryResponseMap), JSON.toJSONString(orderBizUpdateRequest));
                Result<String> result = orderBizAssemble.assemble(queryResponseMap, orderBizUpdateRequest);
                log.info("AbstractOrderBizUpdateService#assembleBizBaseInfo orderBizUpdateRequest={}, result={}", orderBizUpdateRequest, result);
                if (!result.isSuccess()) {
                    return addFailResponse(result);
                }
            }
        } catch (Exception e) {
            log.error("AbstractOrderBizUpdateService#assembleBizBaseInfo assemble error", e);
            throw new FunctionException(e);
        } finally {
            StopWatchUtils.stop();
        }
        return null;
    }

    /*指定单据类型 销售订单Tag：normal，退货订单：return，换货订单：exchange 等等*/
    public abstract String getOrderTag();

    private static OrderAtomUpdateResponse addFailResponse(Result<String> assembleResult) {
        OrderAtomUpdateResponse response = new OrderAtomUpdateResponse();

        if (StringUtils.contains(assembleResult.getResult(), "@")) {
            String[] resultInfoArr = assembleResult.getResult().split("@");
            String salesOrderNo = resultInfoArr[0];
            String sourceLineNum = resultInfoArr[1];
            String productCode = resultInfoArr[2];

            response.setSalesOrderNo(salesOrderNo);
            response.setErrorCode("OC-01-001-01-16-007");
            response.setMessage("订单修改整单失败");

            List<OrderLineAtomCreateResponse> orderDetails = Lists.newArrayList();
            OrderLineAtomCreateResponse lineResponse = new OrderLineAtomCreateResponse();
            lineResponse.setSourceLineNum(sourceLineNum);
            lineResponse.setProductCode(productCode);
            lineResponse.setErrorCode(assembleResult.getErrorCode());
            lineResponse.setMessage(assembleResult.getMessage());
            orderDetails.add(lineResponse);
            response.setOrderDetails(orderDetails);
        } else {
            response.setSalesOrderNo(assembleResult.getResult());
            response.setErrorCode(assembleResult.getErrorCode());
            response.setMessage(assembleResult.getMessage());
        }

        return response;
    }
}
